import requests
from bs4 import BeautifulSoup
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Alignment
import matplotlib.pyplot as plt
import sys
import io

sys.studout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf8')

def write_to_excel(file_path, sheet_name, data):
    """
    将请求的数据写入Excel
    Args:
        file_path(str)： 保存的Excel文件路径
        sheet_name(str): 工作表名称
        data(list): 数据内容
    """
    wb = Workbook()
    sheet = wb.active
    sheet.title = sheet_name
    for row_num, row_data in enumerate(data, start=1):
        for col_num, col_data in enumerate(row_data, start=1):
            cell = sheet.cell(row_num, col_num, col_data)
            cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
    wb.save(file_path)

def fetch_weather_data(url):
    """
    获取天气数据并返回Pandas DataFrame
    Args:
        url(str): 天气数据的URL
    Returns:
        pd.DataFrame: 包含日期、天气情况和气温数据
    """

    response = requests.get(url)
    html = response.content.decode('gbk')
    soup = BeautifulSoup(html, 'html.parser')

    tr_list = soup.find_all('tr')

    dates,conditions,temperatures = [],[],[]
    for data in tr_list[1:]: # 跳过表头行
        sub_data = data.text.split()
        dates.append(sub_data[0])
        conditions.append(''.join(sub_data[1:3]))
        temperatures.append(''.join(sub_data[3:6]))

    # 数据保存到DataFrame中
    weather_data = pd.DataFrame({
        '日期': dates,
        '天气情况': conditions,
        '气温': temperatures
    })
    return weather_data

def visualize_weather_data(data):
    """
    可视化天气数据
    Args:
        data(pd.DataFrame): 天气数据
    """
    # 提取最高气温、最低气温
    data['最高气温'] = data['气温'].str.split('/', expand=True)[0].str.replace('℃', '').astype(int)
    data['最低气温'] = data['气温'].str.split('/', expand=True)[1].str.replace('℃', '').astype(int)

    dates = data['日期']
    highs = data['最高气温']
    lows = data['最低气温']

    # 设置字体和图表参数
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    fig = plt.figure(dpi=128, figsize=(12,6))
    plt.plot(dates, highs, c='red', alpha=0.5, label='最高气温')
    plt.plot(dates, lows, c='blue', alpha=0.5, label='最低气温')
    plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.2)

    # 图表格式
    plt.title('每周最高最低气温', fontsize=24)
    plt.xlabel('日期', fontsize=12)
    plt.ylabel('气温(℃)', fontsize=12)
    plt.tick_params(axis='both', which='major', labelsize=10)

    # 处理横坐标
    tick_interval = max(1, len(dates) // 15) # 每隔一定数量显示一个刻度
    plt.xticks(ticks=range(0, len(dates), tick_interval), labels=dates[::tick_interval], rotation=45)

    plt.legend()
    plt.show()

def main():
    """
    主程序，抓取天气数据，保存到Excel,并进行可视化
    """
    # 天气数据的URL
    urls = [
        'http://www.tianqihoubao.com/lishi/meizhou/month/202405.html',
        'http://www.tianqihoubao.com/lishi/meizhou/month/202406.html',
        'http://www.tianqihoubao.com/lishi/meizhou/month/202407.html'
    ]

    # 抓取天气数据并合并
    weather_data_frames = [fetch_weather_data(url) for url in urls]
    combined_data = pd.concat(weather_data_frames).reset_index(drop=True)

    # 保存到Excel
    excel_path = 'weather_data.xlsx'
    write_to_excel(excel_path, '天气数据', combined_data.values)

    # 可视化
    visualize_weather_data(combined_data)

if __name__ == '__main__':
    main()